import { useMemo } from "react";
import { URLSearchParamsInit, useSearchParams } from "react-router-dom"
import { cleanObject } from ".";

export const useUrlQueryParam = <K extends string>(keys:K[])=>{
    const [searchParams] = useSearchParams();
    const setSearchParams = useSetUrlSearchParam();
    return [
        useMemo(
            ()=>keys.reduce((prev,key)=>{
                return {...prev,[key]:searchParams.get(key) || ''}
            },{} as {[key in K]:string}),
            //eslint-disable-next-line react-hooks/exhaustive-deps
            [searchParams]
        ),
        // 为了在外层set的时候约束更精确，这边不要直接写
        //setSearchParams
        // 只准备一个口
        // (params:Partial<{[key in K]:unknown}>)=>{
        //     //Object.formEntries需要一个可迭代的参数，将其中的键值对列表组成一个对象并返回，searchParams是URLSearchParamsInit，部署了Iterator对象
        //     const o = cleanObject({...Object.fromEntries(searchParams),...params}) as URLSearchParamsInit;
        //     return setSearchParams(o);
        // }
        setSearchParams
    ] as const;
}

export const useSetUrlSearchParam = ()=>{
    const [searchParams,setSearchParam] = useSearchParams();
    return (params:{[key in string]:unknown})=>{
        const o = cleanObject({
            ...Object.fromEntries(searchParams),
            ...params
        }) as URLSearchParamsInit;
        return setSearchParam(o);
    }
}


/**
 * ts的类型推断，默认会把数组、元组推断为数组，里面如果有不同类型的情况就用联合类型
 * 如下面的test，但这样并不精确
 * const断言，会将数组中的值变为只读的字面量类型的元组
 */
// const test = [12,'12',{gender:'male'}];
// const test2 = [12,'12',{gender:'male'}] as const;
